<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <div>
      <button @click="getRequest">发起Get请求</button>
      <button @click="postRequest">发起POST请求</button>
      <button @click="axiosAll">并发执行多个请求</button>
      <button @click="axiosOption">传递相关配置请求</button>
      <button @click="axiosOptionAll">请求完整配置</button>
      <button @click="result = ''" style="background: #c06478; border-color: #c06478;">隐藏结果</button>
    </div>
    <div v-if="result !== ''" class="result-area" v-html="result">
    </div>
    <div class="note">
      <h2>请求配置</h2>
      <pre>
        <b><em>url</em></b>: 'api/mock1', // `url` 是用于请求的服务器 URL
        <b><em>method</em></b>: 'post', // 默认是 get
        <b><em>baseURL</em></b>: 'http://avengers.local/', // 将自动加在 `url` 前面，除非 `url` 是一个绝对 URL
        <b><em>transformRequest</em></b>: [(data) => `（在向服务器发送前，修改请求数据）${JSON.stringify(data)}`],
         //允许在向服务器发送前，修改请求数据，只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法，后面数组中的函数必须返回一个字符串
        <b><em>transformResponse</em></b>: [(data) => {
            let obj = JSON.parse(data)
            obj.content = `（在传递给 then/catch 前，修改响应数据）${JSON.parse(data).content}`
            return obj
        }], // 在传递给 then/catch 前，允许修改响应数据
        <b><em>headers</em></b>: {
          'Content-Type': 'application/json'
        }, // `headers` 是即将被发送的自定义请求头
        <b><em>params</em></b>: { //`params` 是即将与请求一起发送的 URL 参数
            id: 9
        },
        <b><em>paramsSerializer</em></b>: null,// 一个负责 `params` 序列化的函数
        <b><em>data</em></b>: { //`data` 是作为请求主体被发送的数据
          username: 'Nat'
        },
        <b><em>timeout</em></b>: 1000, //请求超时的毫秒数(0 表示无超时时间)，如果请求话费了超过 `timeout` 的时间，请求将被中断
        <b><em>withCredentials</em></b>: false, // 跨域请求时是否需要使用凭证，默认的false
        <b><em>adapter</em></b>: null, //允许自定义处理请求返回一个 promise
        <b><em>auth</em></b>: null, //应该使用 HTTP 基础验证，并提供凭据
        <b><em>responseType</em></b>: 'json', //服务器响应的数据类型默认 json
        <b><em>xsrfCookieName</em></b>: 'XSRF-TOKEN', // 默认的
        <b><em>xsrfHeaderName</em></b>: 'X-XSRF-TOKEN', // 默认的
        <b><em>onUploadProgress</em></b>: null, //允许为上传处理进度事件
        <b><em>onDownloadProgress</em></b>: null, //允许为下载处理进度事件
        <b><em>maxContentLength</em></b>: 2000, // 定义允许的响应内容的最大尺寸
        <b><em>validateStatus</em></b>: (status) => { //定义对于给定的HTTP 响应状态码是 resolve 或 reject 
            return status >= 200 && status &lt; 300; // 默认的resolve 在这个条件下是不会reject错误的
        },
        <b><em>maxRedirects</em></b>: 5, // 默认的，如果设置为0，将不会 允许 任何重定向
        // <b><em>httpAgent</em></b>: new http.Agent({ //用于定义在执行 http 和 https 时使用的自定义代理
        //     keepAlive: false // 默认没有启用
        // }),
        // <b><em>httpsAgent</em></b>: new https.Agent({ //用于定义在执行 http 和 https 时使用的自定义代理
        //     keepAlive: false // 默认没有启用
        // }),
        <b><em>proxy</em></b>: { //'proxy' 定义代理服务器的主机名称和端口
        //   host: '127.0.0.1',
        //   port: 9000,
          auth: { //`auth` 表示 HTTP 基础验证应当用于连接代理，并提供凭据
            // username: 'mikeymike',
            // password: 'rapunz3l'
          }
        },
        // <b><em>cancelToken</em></b>: new CancelToken(function (cancel) {}) //指定用于取消请求的 cancel token
      </pre>
      <h2>拦截器</h2>
      <pre>
        // 拦截请求
        <b><em>axios.interceptors.request.use</em></b>(config => { //config是配置选项的对象
            config.params = {
                tip: `拦截器拦截请求改变params请求参数`,
                ...config.params
            }
            if (config.method === 'post') {
                config.data = {
                  add: '拦截器拦截请求改变data请求参数',
                  ...config.data
                }
            }
            return config
        }, err => {
            return Promise.reject(err)
        })

        // 拦截响应
        <b><em>axios.interceptors.response.use</em></b>(response => {
            if (response.config.baseURL == 'http://avengers.local/') {
                response.data.content = '（拦截器拦截响应）' + response.data.content
            }
            return response
        }, err => {// 拦截错误信息
            return Promise.reject(err)
        })

        // 移除拦截器：
        var myInterceptor = axios.interceptors.request.use(function () {
          /*...*/ });
        <b><em>axios.interceptors.request.eject</em></b>(myInterceptor);

        // 自定义实例添加拦截器
        var instance = <b><em>axios.create()</em></b>;
        instance.interceptors.request.use(function () {
          /*...*/ });
      </pre>
    </div>
  </div>
</template>

<script>
import options from './axios_options'
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Axios 操作区域',
      result: ''
    }
  },
  methods: {
    getRequest(){
      this.$http.get('api/mock1', {
        params: {
          id: 1 //或者直接在 url 后 加 ?id=1
        }
      }).then(res => {
        this.result = decodeURI(res.data.content)
      }).catch(err => {
        console.log(err)
      })
    },
    postRequest(){
      this.$http.post('api/mock1', {
        username: 'Tony'
      }).then(res => {
        this.result = decodeURI(res.data.content)
      }).catch(err => {
        console.log(err)
      })
    },
    axiosAll(){
      const a1 = this.$http.get('api/mock1')
      const a2 = this.$http.post('api/mock2')
      this.$http.all([a1, a2]).then( //两个请求都完成时才回调
        this.$http.spread((val1, val2) => { //spread可对返回的数组进行分割 分割成多个单独的响应对象
          this.result = `${decodeURI(val1.data.content)}<br><br>${decodeURI(val2.data.content)}<br><br>axios.all()组合请求 axios.spread()分割响应`
        })
      )
    },
    axiosOption(){
      this.$http({
        url: 'api/mock1',
        method: 'post',
        data: {
          username: 'Nat'
        },
        params: {
          id: 9
        }
      }).then((res) => {
        this.result = decodeURI(res.data.content)
      }).catch((err) => {
        console.log(err)
      })
    },
    axiosOptionAll(){
      this.$http(options).then((res) => { //encodeURI编码 dncodeURI解码
        this.result = `${decodeURI(res.data.content)}<br><br>响应内容：data、status、statusText、headers、config`
      }).catch((err) => {
        console.log(err)
      })
      //等同于
      // this.$http.create(options).get()
    },
  },
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.result-area{
  border: 1px solid #c06478;
  border-radius: 20px;
  text-align: left;
  width: fit-content;
  padding: 20px;
  margin: 40px auto;
}
.note{
  text-align: left;
  width: fit-content;
  margin: 0 auto;
}
.note pre{
  border: 1px solid #42b983;
  border-radius: 30px;
  padding: 20px;
  font-size: 16px;
  line-height: 26px;
}
.note pre em{
  color: #42b983;
}
</style>
